<template>
  <div class="qr-code" v-loading="loading" :style="{width:`${width}px`,height:`${height}px`,padding:`${padding}px`}">
    <div class="qr-error login-tips" v-if="!hasLogin">
      <el-button size="small" type="primary" @click="$emit('login')">
        <span>
          {{ $t('login.log') }}
        </span>
      </el-button>
    </div>
    <div class="refresh qr-error" v-else-if="!isAgree" @click="handleAgree">
      <span>
        {{ $t('code.agree') }}
      </span>
    </div>
    <div class="code-box"
      v-show="hasLogin">
      <div
        ref="qrCode"
        key="code">
      </div>
      <div v-show="payMsg"
        class="refresh qr-error"
        :class="{ loading: payLoading }"
        key="refresh"
        @click="refreshCode">
        <div class="pay-tip" v-if="payMsg">
          <svg-icon :icon-class="payMsgIcon" />
          <p>{{ payMsg }}</p>
        </div>
      </div>
    </div>
  </div>
</template>
<script>

import QRCode from 'qrcodejs2'
import { createOrderApi, getOrderInfoApi, checkOrderInfo } from './api'
import { debounce } from '@/utils'

export default {
  name: 'HkWxPaymentCode',
  props: {
    isShow: {
      type: Boolean,
      default: true
    },
    hasLogin: {
      type: Boolean,
      default: false
    },
    product: {
      type: Object,
      require: true
    },
    needAgree: {
      type: Boolean,
      default: false
    },
    otherParamsStr: {
      type: String,
      default: '{}'
    },
    width: {
      type: Number,
      default: 150
    },
    height: {
      type: Number,
      default: 150
    },
    padding: {
      type: Number,
      default: 10
    },
    payLoading: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      isOnShow: true,
      loading: false,
      qrcode: null,
      timer: null,
      payMsg: '',
      payMsgIcon: '',
      invalidTime: null,
      isAgree: true
    }
  },
  watch: {
    needAgree: {
      handler (newVal) {
        this.isAgree = !newVal
      },
      immediate: true
    },
    'product.id': {
      handler () {
        if (this.createOrder_) {
          this.createOrder_()
        } else {
          this.createOrder()
        }
      },
      immediate: true
    },
    otherParamsStr () {
      this.createOrder_()
    },
    'isShow' () {
      this.createOrder_()
    },
    'hasLogin' () {
      this.createOrder_()
    }
  },
  mounted () {
    const container = this.$refs.qrCode
    this.qrcode = new QRCode(container, {
      text: this.text,
      width: this.width - this.padding * 2,
      height: this.height - this.padding * 2,
      colorDark: '#000000',
      colorLight: '#ffffff',
      correctLevel: 0
    })
  },
  activated () {
    this.isOnShow = true
    this.createOrder()
  },
  deactivated () {
    this.isOnShow = false
    this.createOrder()
  },
  beforeDestroy () {
    this.isOnShow = false
    this.createOrder()
  },
  created () {
    this.createOrder_ = debounce(() => {
      this.createOrder()
    }, 250, false)
  },
  methods: {
    setMsg (msg, icon = 'code-refresh') {
      this.payMsg = msg
      this.payMsgIcon = icon
    },
    handleAgree () {
      this.$emit('agree')
      this.isAgree = !this.isAgree
    },
    refreshCode () {
      if (this.payLoading) {
        return
      }
      this.$emit('refresh')
      this.clearOrder()
      this.createOrder()
    },
    cancelCheckOrder () {
      if (this.timer) {
        clearTimeout(this.timer)
      }
      this.clearOrder()
      this.setCodeError()
    },
    setTime (oldCode) {
      clearTimeout(this.timer)
      if (this.invalidTime < Date.now()) {
        this.setMsg(this.$t('payment.timeout'))
        this.emitOrderStatus('timeout')
        return
      }
      this.timer = setTimeout(() => {
        if (this.error || this.paySuccess || oldCode !== this.product.orderid) return
        oldCode = this.product.orderid
        checkOrderInfo({ orderid: this.product.orderid, sign: this.product.sign, type: 'hk_wx' }).then(res => {
          if (oldCode !== this.product.orderid) return
          const data = res.data || {}
          if (data.status === 0) {
            this.emitOrderStatus('succes')
            this.setMsg(this.$t('payment.paySuccess'), 'success')
          } else if (data.status === 2) {
            this.setMsg(this.$t('payment.invalid'))
            this.emitOrderStatus('error')
          }
          this.setTime(oldCode)
        }).catch(() => {
          this.setTime(oldCode)
        })
      }, 3000)
    },
    createOrder () {
      clearTimeout(this.timer)
      if ([!this.isOnShow, !this.hasLogin, !this.product.id].includes(true)) return
      if (this.product.orderid && this.product.otherParamsStr === this.otherParamsStr) {
        const invalidTime = this.product.invalidTime
        if (invalidTime > Date.now()) {
          this.payMsg = ''
          this.makePayCode()
          return
        }
      }
      const params = {
        product_id: [this.product.id],
        pay_way: 9,
        pay_entry: 'web',
        channel_id: this.$store.getters.appInfo.channel
      }
      const otherParamsStr = this.otherParamsStr || '{}'
      const otherParams = JSON.parse(otherParamsStr)

      // if (otherParams.noproduct) {
      //   params.product_id = []
      // }
      if (otherParams.couponid) {
        params.coupon_id = otherParams.couponid
      }
      if (otherParams.actids) {
        const ids = otherParams.actids.split(',')
        params.act_ids = ids.map(id => parseInt(id))
      }
      // if (otherParams.giveproduct) {
      //   params.give_product = otherParams.giveproduct
      // }
      // if (otherParams.addproduct) {
      //   params.add_product_id = otherParams.addproduct
      // }
      this.loading = true
      createOrderApi(params).then(res => {
        const oldId = params.product_id[0] || this.product.id
        if (this.product.id !== oldId) {
          this.loading = false
          return
        }
        this.getOrderInfo(res.data || {}, oldId, otherParamsStr)
      }).catch(() => {
        this.setCodeError()
      })
    },
    getOrderInfo (data, oldId, otherParamsStr) {
      if (!data.order_id) {
        this.setCodeError()
        return
      }
      // this.$xzAsy('xz_get_merchant_token').then(res => {
      const orderInfo = {
        type: 'hk_wx',
        orderId: data.order_id,
        sign: data.sign,
        title: data.title,
        appID: process.env.VUE_APP_ID,
        payAppId: 'wxdac9724d6d82b659',
        trade_method: 'NATIVE'
      }
      getOrderInfoApi(orderInfo).then(res => {
        this.loading = false
        if (this.product.id !== oldId) return
        this.payMsg = ''
        const data = res.data
        this.product.invalidTime = (data.expire || 600) * 1000 + Date.now()
        this.product.payURL = data.payURL
        this.product.orderid = orderInfo.orderId
        this.product.sign = orderInfo.sign
        this.product.otherParamsStr = otherParamsStr
        this.makePayCode()
      }).catch(() => {
        this.setCodeError()
      })
      // }).catch(() => {
      //   this.setCodeError()
      // })
    },
    setCodeError () {
      this.setMsg(this.$t('payment.refresh'))
      this.loading = false
    },
    makePayCode () {
      const payURL = this.product.payURL
      this.invalidTime = this.product.invalidTime
      if (this.qrcode) {
        this.qrcode.makeCode(payURL)
        this.qrcode._el.title = ''
        this.setTime(this.product.orderid)
      }
    },
    clearOrder () {
      this.product.payURL = null
      this.product.orderid = null
      this.product.sign = null
      this.product.otherParamsStr = null
      this.product.invalidTime = null
    },
    emitOrderStatus (status) {
      this.clearOrder()

      if (status === 'succes') {
        this.$emit('onStatusChange', status)
      }
    }
  }
}
</script>
<style lang="scss" scoped>
@import "./index.scss";

.loading {
  cursor: not-allowed !important;

  .svg-icon {
    cursor: not-allowed !important;
  }
}

.pay-tip {
  display: flex;
  flex-flow: column nowrap;
  row-gap: 10px;
  justify-content: center;
  align-items: center;

  .svg-icon {
    position: relative !important;
  }

  p {
    font-size: 12px;
    color: #fff;
  }
}
</style>
